<template>
  <el-card class="box-card">
    <div class="search">
      <el-input v-if="isValueExists('menu-getmenupage')" v-model="listQuery.searchString" placeholder="请输入关键字" style="width: 400px;" />
      <el-button v-if="isValueExists('menu-getmenupage')" class="button" :icon="initIcon('Search')" type="primary" @click.prevent="menuQuery">查询</el-button>
      <el-button v-if="isValueExists('menu-editmenu')" class="button" :icon="initIcon('Plus')" @click.prevent="addInfo">新增</el-button>
    </div>
    <el-table :data="tableData" style="width: 100%; margin-bottom: 20px" row-key="id" border default-expand-all
      :tree-props="{ children: 'childMenus', hasChildren: 'hasChildren' }">
      <el-table-column prop="menuText" label="菜单名称" sortable>
        <template #default="{ row }">
          <el-icon>
            <component :is="initIcon(row.icon)"></component>
          </el-icon>
          {{ row.menuText }}
        </template>
      </el-table-column>
      <el-table-column prop="menuType" label="菜单类型" sortable>
        <template #default="{ row }">
          <el-tag :type="row.menuType == 0 ? 'success' : row.menuType == 1 ? 'warning' : ''">
            {{ menuTypeFilter(row.menuType) }}
          </el-tag>
        </template>
      </el-table-column>
      <el-table-column prop="status" label="状态">
        <template #default="{ row }">
          <el-tag :type="tagFilter(row.status)">
            {{ StatusType(row.status) }}
          </el-tag>
        </template>
      </el-table-column>
      <el-table-column prop="routeName" label="路由名称" sortable />
      <el-table-column prop="webUrl" label="前端URL地址" sortable />
      <el-table-column fixed="right" label="操作">
        <template #default="{ row }">
          <div>
            <el-button v-if="isValueExists('menu-editmenu')" link type="primary" size="small" @click.prevent="editInfo(row)">编辑</el-button>
            <el-button v-if="isValueExists('menu-removemenu')" link type="danger" size="small" @click="removeInfo(row.id)">删除</el-button>
          </div>
          <div>
            <el-button v-if="isValueExists('menu-freezemenu')" link type="info" size="small" @click="freezeInfo(row.id)">
              {{ row.status == -1 ? '解冻' : '冻结' }}
            </el-button>
          </div>
        </template>
      </el-table-column>
    </el-table>
    <!-- 分页 -->
    <div class="pagination">
      <el-pagination background layout="prev, pager, next, sizes" :total="totalCount" :hide-on-single-page="isHide"
        @size-change="handleSizeChange" @current-change="handleCurrentChange" />
    </div>
  </el-card>

  <!-- 菜单编辑 -->
  <el-dialog v-model="dialogVisible" :title="modifyWindowTitle" width="30%" :before-close="handleClose">
    <el-form ref="ruleFormRef" :model="menuInfo" :rules="rules" label-width="110px">
      <el-form-item label="所属菜单" prop="parentId">
        <el-tree-select v-model="menuInfo.parentId" :data="selectData.value" class="m-2" :render-after-expand="false"
          placeholder="请选择所属菜单" check-strictly="true" @change="selectedChange" :prop="selectProp">
        </el-tree-select>
      </el-form-item>
      <el-form-item label="菜单名称" prop="menuText">
        <el-input v-model="menuInfo.menuText" />
      </el-form-item>
      <el-form-item label="路由名称" prop="routeName">
        <el-input v-model="menuInfo.routeName" />
      </el-form-item>
      <el-form-item label="Vue组件路径" prop="vueFilePath">
        <el-input v-model="menuInfo.vueFilePath" />
      </el-form-item>
      <el-form-item label="图标">
        <el-select v-model="menuInfo.icon" placeholder="请选择" class="m-2">
          <el-option v-for="item in iconSource.value" :key="item.value" :label="item.label" :value="item.value">
            <span style="float: left">
              <el-icon>
                <component :is="initIcon(item.value)" />
              </el-icon>
            </span>
            <span style="
          float: right;
          color: var(--el-text-color-secondary);
          font-size: 13px;
        ">{{ item.label }}</span>
          </el-option>
        </el-select>
      </el-form-item>
      <el-form-item label="是否启用">
        <el-switch v-model="menuInfo.status" />
      </el-form-item>
    </el-form>
    <template #footer>
      <span class="dialog-footer">
        <el-button @click="closeWindow">取消</el-button>
        <el-button type="primary" @click="submit(ruleFormRef)">确定</el-button>
      </span>
    </template>
  </el-dialog>
</template>

<script setup>
import { reactive, ref, onMounted, computed, markRaw, onBeforeMount } from 'vue';
import axios from '@/api'
import { InitIcon, IconSource, StatusType, currentMenuPermission } from '@/common'
import { ElMessage, ElMessageBox } from 'element-plus'
import { useRouter } from "vue-router";

const listQuery = reactive({
  pageIndex: 1,
  pageSize: 10,
  searchString: ''
});
const tableData = ref([]);
const totalCount = ref(0);
const isHide = ref(false);
const dialogVisible = ref(false)
const modifyWindowTitle = ref('新增');
const ruleFormRef = ref();
const iconSource = reactive([]);
const menuInfo = reactive({
  id: '00000000-0000-0000-0000-000000000000',
  parentId: '00000000-0000-0000-0000-000000000000',
  menuText: '',
  fullName: '',
  controllerName: '',
  actionName: '',
  menuType: 1,
  icon: '',
  routeName: '',
  webUrl: '',
  vueFilePath: '',
  isLeafNode: true,
  status: 1
});
const selectData = reactive([]);
const selectProp = ref({
  value: 'value',
  label: 'label',
  children: 'children'
})
const btnArray = reactive([]);

//#region 文本格式化
const menuTypeFilter = computed(() => item => {
  switch (item) {
    case 0:
      return '菜单'
    case 1:
      return '按钮'
  }
});

const tagFilter = computed(() => item => {
  switch (item) {
    case 1:
      return 'success';
    case 0:
      return 'info'
    case -1:
      return 'warning'
    default:
      return 'danger'
  }
});

const initIcon = (strIcon) => {
  return InitIcon(strIcon);
}
//#endregion

//#region 表单校验
const checkMenu = async (rule, value, callback) => {
  if (value !== '00000000-0000-0000-0000-000000000000' && value === menuInfo.value.id) {
    callback(new Error('请选择所属菜单'))
  } else {
    callback();
  }
}

const rules = reactive({
  menuText: [
    {
      required: true,
      message: '请输入菜单名称',
      trigger: 'blur'
    }
  ],
  parentId: [
    {
      required: true,
      validator: checkMenu,
      trigger: 'change'
    }
  ],
  routeName: [
    {
      required: true,
      message: '请输入路由名称',
      trigger: 'blur'
    }
  ],
  webUrl: [
    {
      required: true,
      message: '请输入前端Url地址',
      trigger: 'blur'
    }
  ],
  vueFilePath: [
    {
      required: true,
      message: '请输入Vue文件路径',
      trigger: 'blur'
    }
  ]
});
//#endregion

//#region 方法
onBeforeMount(() => {
  var menuId = useRouter().currentRoute.value.meta.id;
  btnArray.value = currentMenuPermission(menuId);
})

onMounted(() => {
  iconSource.value = IconSource();

  keydownEvent();
  menuQuery();
})

const keydownEvent = () => {
  document.onkeydown = (e) => {
    if (e.defaultPrevented) {
      return;
    }

    const body = document.getElementsByTagName('body')[0];
    if (e.key === 'Enter') {
      menuQuery();
    }
  }
}

//角色查询
const menuQuery = async () => {
  //向后端发送请求，获取用户数据
  let url = `Menu/${listQuery.pageIndex}/${listQuery.pageSize}/${listQuery.searchString}`;
  let { data } = await axios.get(url);

  let { data: d, success, message } = data;

  if (success) {
    // 表格数据
    tableData.value = d.dataList;
    totalCount.value = d.recordCount;
  } else {
    ElMessage({
      type: "warning",
      message: message
    });
  }

  isHide.value = d.length === 0;
}

//添加菜单
const addInfo = async () => {
  modifyWindowTitle.value = '新增';

  if (ruleFormRef.value !== undefined) {
    ruleFormRef.value.resetFields();
  }

  await GetMenuSelectData();

  dialogVisible.value = true;
}

const GetMenuSelectData = async () => {
  selectData.value = [];

  let { data } = await axios.get('/Menu/GetMenusSelectList');
  let { data: d, success, message } = data;

  if (!success) {
    ElMessage({
      type: "warning",
      message: message
    });

    return;
  }

  selectData.value = d;
}

//提交
const submit = async (formEl) => {
  if (!formEl) return
  //校验
  await formEl.validate(async (valid, fields) => {
    if (!valid) {
      ElMessage({
        type: 'warning',
        message: '验证失败，请正确输入信息后再提交'
      });

      return;
    }
  });

  menuInfo.status = menuInfo.status === true ? 1 : 0;

  if (menuInfo.id === '00000000-0000-0000-0000-000000000000' || menuInfo.id === '') {
    let { data } = await axios.post('Menu', menuInfo.value);
    let { data: d, success, message } = data;

    if (!success) {
      ElMessage({
        type: 'error',
        message: message
      });

      return;
    }
  } else {
    let { data } = await axios.put('Menu', menuInfo);
    let { data: d, success, message } = data;

    if (!success) {
      ElMessage({
        type: 'error',
        message: message
      });

      return;
    }
  }

  ElMessage({
    type: 'success',
    message: '保存成功'
  });

  dialogVisible.value = false;

  await menuQuery();
}

//切换页大小
const handleSizeChange = (val) => {
  listQuery.pageSize = val;
  roleQuery();
}

//翻页
const handleCurrentChange = (val) => {
  listQuery.pageIndex = val;
  roleQuery();
}

//窗体关闭
const closeWindow = () => {
  dialogVisible.value = false;
}

//窗体关闭
const handleClose = (done) => {
  done();
}

//父级菜单选项改变
const selectedChange = (value) => {
  menuInfo.value.parentId = value;
}

//编辑
const editInfo = async (row) => {
  modifyWindowTitle.value = '新增'
  dialogVisible.value = true;

  if (ruleFormRef.value !== undefined) {
    ruleFormRef.value.resetFields();
  }

  await GetMenuSelectData();

  menuInfo.id = row.id;
  menuInfo.parentId = row.parentId;
  menuInfo.menuText = row.menuText;
  menuInfo.vueFilePath = row.vueFilePath;
  menuInfo.routeName = row.routeName;
  menuInfo.icon = row.icon;
  menuInfo.status = row.status === 1;
  menuInfo.fullName = row.fullName;
  menuInfo.controllerName = row.controllerName;
  menuInfo.actionName = row.actionName;
  menuInfo.menuType = row.menuType;
  menuInfo.icon = row.icon;
  menuInfo.webUrl = row.webUrl;
  menuInfo.isLeafNode = row.isLeafNode;
}

//删除
const removeInfo = async (id) => {
  ElMessageBox.confirm('是否删除？', '提醒', {
    type: 'warning',
    icon: markRaw(initIcon('Delete'))
  })
    .then(async () => {
      let { data } = await axios.delete(`/Menu/${id}`);
      let { success, message } = data;

      if (success) {
        ElMessage({
          type: "success",
          message: "删除成功"
        });

        await menuQuery();
      } else {
        ElMessage({
          type: "warning",
          message: message
        });
      }
    })
    .catch(() => {
      ElMessage({
        type: "warning",
        message: '操作已取消'
      });
    })
}

//冻结
const freezeInfo = async (id) => {
  let { data } = await axios.put(`/Menu/${id}`);
  let { success, message } = data;

  if (success) {
    ElMessage({
      type: "success",
      message: "冻结成功",
      icon: markRaw(initIcon('Success'))
    });

    await menuQuery();
  } else {
    ElMessage({
      type: "warning",
      message: message
    });
  }
}

const isValueExists = (item) => {
  var arr = btnArray.value.filter(b => b.btnValue === item);

  return arr.length > 0;
}
//#endregion

</script>